﻿using Autofac.Extensions.DependencyInjection;
using Autofac;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace WorkerService.Common
{
    public static class AutofacUtil
    {
        public static IHostBuilder AddAutofac(this IHostBuilder host)
        {
            //Autofac替换内置DI
            host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
            host.ConfigureContainer<ContainerBuilder>(containerBuilder => containerBuilder.RegisterModule(new AutofacRegisterModule()));
            return host;

            //注入方式,默认瞬时
            //一般使用瞬时和单例即可

            //瞬时
            //containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerDependency().PropertiesAutowired();

            //单例：
            //containerBuilder.RegisterType<UserService>().As<IUserService>().SingleInstance().PropertiesAutowired();

            //每个生命周期范围一个实例
            //containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope().PropertiesAutowired();

            //Web请求范围一个实例
            //containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerRequest().PropertiesAutowired();          
        }
    }


    /// <summary>
    /// Ioc管理
    /// </summary>
    public static class IocManager
    {
        private static ILifetimeScope _container { get; set; }

        public static void InitContainer(this IServiceProvider serviceProvider)
        {
            _container ??= serviceProvider.GetAutofacRoot();
        }

        /// <summary>
        /// 获取实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetService<T>() where T : notnull
        {
            return _container.Resolve<T>();
        }

        /// <summary>
        /// 获取实例
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object GetService(Type type)
        {
            return _container.Resolve(type);
        }

        /// <summary>
        /// 获取实例(一对多)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetService<T>(Type type) where T : notnull
        {
            return GetServices<T>().FirstOrDefault(a => a.GetType().Equals(type)) ?? _container.Resolve<T>();
        }

        /// <summary>
        /// 获取实例列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> GetServices<T>() where T : notnull
        {
            return _container.Resolve<IEnumerable<T>>();
        }

        /// <summary>
        /// 判断是否注入
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool IsRegistered<T>()
        {
            return _container.IsRegistered<T>();
        }

        /// <summary>
        /// 判断是否注入
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool IsRegistered(Type serviceType)
        {
            return _container.IsRegistered(serviceType);
        }
    }

    public class AutofacRegisterModule : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            //批量自动注入,把需要注入层的程序集传参数
            BatchRegister(builder, typeof(AutofacRegisterModule).Assembly);
        }
        /// <summary>
        /// 批量注入扩展
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assembly"></param>
        private void BatchRegister(ContainerBuilder builder, Assembly assembly)
        {
            Type transientType = typeof(ITransitDenpendency);
            Type singletonType = typeof(ISingletonDenpendency);
            Type scopeType = typeof(IScopeDenpendency);

            //.EnableInterfaceInterceptors();后面加载此方法使用拦截器
            builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(transientType))
                .AsSelf().AsImplementedInterfaces().InstancePerDependency().PropertiesAutowired();

            builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(singletonType))
               .AsSelf().AsImplementedInterfaces().SingleInstance().PropertiesAutowired();

            builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(scopeType))
               .AsSelf().AsImplementedInterfaces().InstancePerLifetimeScope().PropertiesAutowired();
        }
    }

    public class User
    {
        public int Age { get; set; }
    }


    /// <summary>
    /// 瞬时注入
    /// </summary>
    public interface ITransitDenpendency
    { }

    /// <summary>
    /// 单例注入标识
    /// </summary>
    public interface ISingletonDenpendency
    { }

    /// <summary>
    /// 生命周期注入标识
    /// </summary>
    public interface IScopeDenpendency
    { }

}
